<?php

require_once('xml2json.php');

class DwcaProcess
{
	private function getService() {
		return array('url' => 'http://gni.globalnames.org/parsers.json', 'params' => array('names' => ''));
	}
	private function getDeLimiter() {
		$coreAttributes = $this->get('coreAttributes');
		switch($coreAttributes->fieldsTerminatedBy) {
			case '\t':
				$chr = "\t";
				break;
			case ',':
			default:
				$chr = ",";
				break;
		}
		return $chr;
	}
	private function getTypesArray() {
		$typesArray = array(
			 'scientificName' => 'http://rs.tdwg.org/dwc/terms/scientificName'
			, 'genus' => 'http://rs.tdwg.org/dwc/terms/genus'
			, 'specificEpithet' => 'http://rs.tdwg.org/dwc/terms/specificEpithet'
			, 'infraspecificEpithet' => 'http://rs.tdwg.org/dwc/terms/infraspecificEpithet'
			);
		return $typesArray;
	}

	private function extractFromZipFile($zipFile,$extractFileName,$extractFilePath) {
		if(!file_exists($zipFile)) {$this->set('errorCode',101);return false;}
		$zip = new ZipArchive;
		if ($zip->open($zipFile) !== TRUE) { $this->set('errorCode',101);return false;}
		$index =  $zip->locateName($extractFileName, ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR);
		$extractFile = $zip->getNameIndex($index);
		$pth = 'zip://'.$zipFile.'#' . $extractFile;
		copy($pth, $extractFilePath . basename($extractFile));
		$zip->close();
		return true;
	}
	private function rewriteZipFile($zipFile,$fileName,$replacementFile) {
		if(!file_exists($zipFile)) {$this->set('errorCode',101);return false;}
		if(!file_exists($replacementFile)) {return false;}
		$zip = new ZipArchive;
		if ($zip->open($zipFile) !== TRUE) { $this->set('errorCode',101);return false;}
		$index =  $zip->locateName($fileName, ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR);
		$fileName = $zip->getNameIndex($index);
		if($zip->deleteName($fileName)) {
			if($zip->addFile($replacementFile,$fileName)) {
				$zip->close();
				return true;
			}
		}
		$zip->close();
		return false;
	}
	public function __construct($db = null){
		$this->db = $db;
	}
	public function get($property) {
		return (isset($this->{$property})) ? $this->{$property} : false;
	}
	public function set($property,$value) {
		$this->{$property} = $value;
		return true;
	}
	public function extractMetaFile() {
		# extracting metafile
		$zipFile = $this->get('sourcePath');
		if(false == $zipFile) return false;
		$metaFilePath = $this->get('metaFilePath');
		if($metaFilePath == '') {
			$metaFilePath =  sys_get_temp_dir() . '/';
			$this->set('metaFilePath',$metaFilePath);
		}
		if(false == $this->extractFromZipFile($zipFile, 'meta.xml', $metaFilePath)) {
			return(false);
		}
		return true;
	}
	public function getMetaFile() {
		# getting data from metafile
		$metaFile = $this->get('metaFilePath') . 'meta.xml';
		if(!@file_exists($metaFile)) {
			$this->extractMetaFile();
		}
		clearstatcache();
		$metaObj = json_decode(@str_replace("@",'',xml2json::transformXmlStringToJson(@file_get_contents($metaFile))));
		$this->set('coreAttributes',$metaObj->archive->core->attributes);
		$this->set('location',$metaObj->archive->core->files->location);
		$feilds = array();
		$flds = $metaObj->archive->core->field;
		$typesArray = $this->getTypesArray();
		$mapArray = array();
		if(is_array($flds) && count($flds)) {
			foreach($flds as $fld) {
				if(false !== ($trm = array_search($fld->attributes->term,$typesArray))) {
					$mapArray[$trm] = $fld->attributes->index;
				}
			}
		}
		$this->set('id',$metaObj->archive->core->id->attributes->index);
		$this->set('mapArray',$mapArray);
		return true;
	}

	public function processCoreFile() {
		# extracting corefile
		$zipFile = $this->get('sourcePath');
		if(false == $zipFile) return false;
		$coreFileName = $this->get('location');
		if(false == $coreFileName) return false;
		$coreFilePath = $this->get('metaFilePath');
		if(false == $this->extractFromZipFile($zipFile,$coreFileName,$coreFilePath)) {return false;}
		$coreFile = $coreFilePath . $coreFileName;
		if(!file_exists($coreFile)){return false;}
// 		$newFile = $coreFilePath . 'newFile.csv';
		$newFile = $coreFilePath . $this->get('output_file');
		$this->set('newFile',$newFile);

		$mapArray = $this->get('mapArray');

		# creating tab limited txt file to populate
		if ( (($csvHandle = fopen($coreFile, 'r'))!== FALSE) && (($newFileHandle = fopen($newFile, 'w')) !== FALSE) ) {
			$count = 0;$i=0;$autoincrement=0;
			$chr = $this->getDeLimiter();
			$service = $this->getService();
			$headerArray = array('scientificName','suggestion1','suggestion2','suggestion3','suggestion4','suggestion5','Response Type');
			$blacklistArray = array();
			while (($fileData = fgetcsv($csvHandle, 1000, $chr )) !== FALSE) {
				if(++$i <=1 ) {
					fwrite($newFileHandle,implode($chr, $headerArray) . "\n");
					continue;
				} # escaping the header row
				$populateArray = array();
				if($mapArray['scientificName'] != '') {
					$sciName = $fileData[$mapArray['scientificName']];
				} else {
					$sciName = $fileData[$mapArray['genus']] . ' ' . $fileData[$mapArray['species']] . ' ' .$fileData[$mapArray['infraspecies']];
				}
				if(in_array($sciName,$blacklistArray)) continue;
				$blacklistArray[] = $sciName;

				$tm = new Taxamatch($this->db);
				if( $tm->process($sciName) ) {
					$tm->generateResponse(false);
				}
				$data = $tm->getData('flat');

				$data = $tm->getData('flat');
				$flg = false;
				$pData = array();
				if(is_array($data) && count($data)) {
					foreach($data as $dt) {
						if($dt['rank'] == 'genus') continue;
						if($dt['rank'] == 'species') {
							$pData[] = $dt;
							$flg = true;
							if($dt['match_type'] == 'exact') {
								$flg = false;
								$pData = array();
								break;
							}
						}
					}
					if(count($pData)) {
						$populateArray[] = $sciName;
						for($i=0;$i<5;$i++) {
							$populateArray[] = $pData[$i]['genus_species'];
						}
						$populateArray[] = '';
					} else if($flg) {
						$populateArray = array($sciName,'','','','','','Not Found');
					}
				} else {
					$populateArray = array($sciName,'','','','','','Not Found');
				}
				if(count($populateArray)) {
					fwrite($newFileHandle,implode($chr, $populateArray) . "\n");
				}

			} # while
			fclose($csvHandle);
			fclose($newFileHandle);
		} # if

/*		header("Content-type: application/octet-stream");
		header("Content-Disposition: attachment; filename=\"" . $this->data['output_file'] . "\"");
		$fp = fopen( $newFile, 'r');
		fpassthru($fp);
		fclose($fp);*/

		@unlink($this->get('metaFilePath').'meta.xml');
		@unlink($this->get('metaFilePath').$this->get('location'));
		@unlink($this->get('sourcePath'));

		return true;
	}

	public function downloadFile() {
		header("Content-type: application/octet-stream");
		header("Content-Disposition: attachment; filename=\"" . @basename($this->get('output_file')) . "\"");
		$fp = fopen( $this->get('newFile'), 'r');
		fpassthru($fp);
		fclose($fp);
		@unlink($this->get('newFile'));
	}

}
?>